keywords = [
    'begin', 'end',

    'var', 'let', 'const', 'is',
    'for', 'from', 'to', 'in',
    'if', 'else',
    'function', 'return',

    'import', 'include'
]

numberTypes = ['TT_INT', 'TT_FLOAT', 'TT_CHAR', 'TT_STRING', 'TT_BOOLEAN', 'TT_NULL']

constants = {
    'These constants are types of Token.':
        ['TT_EOF',
         'TT_SIGN', 'TT_NAME', 'TT_KEYWORD', 'TT_OPERATION',
         *numberTypes],
    'These constants are values of Token.':
        ['TV_EOF',
         'TV_ADD', 'TV_SUB', 'TV_MUL', 'TV_DIV', 'TV_MOD', 'TV_EQ', {'TV_SET_VALUE': f'Keywords.IS.obj.value'},
         'TV_COMMA', 'TV_POINT', 'TV_LP1', 'TV_RP1'],
    'These constants can help lexer to create token stream.':
        [
            {'TH_NUMBERS': '\'1234567890\''},
            {'TH_LETTERS': '\'' + ''.join([chr(i)for i in range(97, 123)]) + ''.join([chr(i)for i in range(65, 91)]) + '\''},
            {'TH_KEYWORDS': [f'Keywords.{keyword.upper()}' for keyword in keywords]},
            {'TH_NUMBERTYPES': [type for type in numberTypes]},
            {'TH_LEFT_UNARY_OPERATORS': ['TV_ADD', 'TV_SUB']},
            {'TH_RIGHT_UNARY_OPERATORS': []},
            {'TH_BINARY_OPERATOR': ['TV_ADD', 'TV_SUB', 'TV_MUL', 'TV_DIV', 'TV_MOD', 'TV_EQ', 'TV_POINT']}
        ]
}

with open('constants.py', 'w') as o:
    o.write('')

with open('constants.py', 'a') as o:
    o.write('from pml import PML\n')

    o.write('\n\n# The object is file namespace.\n#   The namespace stores all keywords.\nclass Keywords:\n')

    for keyword in keywords:
        o.write(f'\t{keyword.upper()} = PML.object.ChangeObject.PMLString_FromStr(\'{keyword}\')\n')

    o.write('\n')

    for i in constants:
        o.write(f'\n# {i}\n')
        for const in constants[i]:
            if isinstance(const, str):
                o.write(f'{const} = PML.object.ChangeObject.PMLObject_FromPythonObject(\'{const}\')\n')
            elif isinstance(const, dict):
                for name in const:
                    if isinstance(const[name], list):
                        o.write(f'{name} = PML.object.ChangeObject.PMLList_FromList([{", ".join(const[name])}])\n')
                    else:
                        o.write(f'{name} = PML.object.ChangeObject.PMLObject_FromPythonObject({const[name]})\n')
